//
// Created by wxd on 2025/7/28.
//

#include "TrackBallCameraControl.h"

#include "../utils/RenderEngineLogger.h"
#include "glm/ext/quaternion_trigonometric.hpp"

void TrackBallCameraControl::setMouseSensitivity(float sensitivity) {
    m_MouseSensitivity = sensitivity;
}

void TrackBallCameraControl::setSyntropy(bool isSyntropy) {
    m_isSyntropy = isSyntropy;
}

void TrackBallCameraControl::setTrackBallAutoRotateSpeed(float speed) {
    m_TrackBallAutoRotateSpeed = speed;
}

void TrackBallCameraControl::setTrackBallRadius(float radius) {
    m_TrackBallRadius = radius;
}

void TrackBallCameraControl::setEnableRotateCenterSelf(bool enableRotateCenterSelf) {
    m_EnableRotateCenterSelf = enableRotateCenterSelf;
}

void TrackBallCameraControl::setLookAtCenter(const glm::vec3 &lookAtCenter) {
    m_LookAtCenter = lookAtCenter;
}

void TrackBallCameraControl::setEnableEulerAnglePitch(bool enable) {
    m_EnableEulerAnglePitch = enable;
}

void TrackBallCameraControl::setEnableEulerAngleYaw(bool enable) {
    m_EnableEulerAngleYaw = enable;
}


void TrackBallCameraControl::onCursor(float xpos, float ypos) {
    BaseCameraControl::onCursor(xpos, ypos); // 调用父类更新鼠标位置信息

    if (m_MouseStatus.isLeftMouseDown) {
        // 处理鼠标左键事件
        float deltaX = xpos - m_MouseStatus.downMousePosX; // 用于计算pitch角
        float deltaY = ypos - m_MouseStatus.downMousePosY; // 用于计算yaw角

        Log.msg("TrackBallCameraControl::onCursor")
            .param("xpos", std::to_string(xpos))
            .param("ypos", std::to_string(ypos))
            .param("deltaX", std::to_string(deltaX))
            .param("deltaY", std::to_string(deltaY)).d();

        // 由于相对运动是相反的，如果相机朝左侧运动，则模型一定朝着右侧运动
        onRotateAlongTrackBall(deltaX * m_MouseSensitivity, deltaY * m_MouseSensitivity);
    } else if (m_MouseStatus.isMiddleMouseDown) {
        // 处理鼠标中键事件

    }
}

void TrackBallCameraControl::onScroll(double yoffset) {

}

void TrackBallCameraControl::onRotateAlongTrackBall(float angleX, float angleY) {
   if (m_RotateType == RotateType::EULER) {
       yawUpdate(angleX);
       pitchUpdate(angleY);
   } else if (m_RotateType == RotateType::QUAT) {
       
   }
}


bool TrackBallCameraControl::isUnMove() const {
    return m_MouseStatus.curMousePosX == 0.f && m_MouseStatus.curMousePosY == 0.f;
}

void TrackBallCameraControl::pitchUpdate(const float angle) {
    if (m_EnableEulerAnglePitch) {
        auto rotateMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(-angle), m_Camera->m_Right);
        m_Camera->m_Position = rotateMatrix * glm::vec4(m_Camera->m_Position, 1.0);
        m_Camera->m_Up = rotateMatrix * glm::vec4(m_Camera->m_Up, 0.0);
    }
}

void TrackBallCameraControl::yawUpdate(const float angle) {
    if (m_EnableEulerAngleYaw) {
        auto rotateMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(-angle), m_Camera->m_Up);
        m_Camera->m_Position = rotateMatrix * glm::vec4(m_Camera->m_Position, 1.0);
        m_Camera->m_Right = rotateMatrix * glm::vec4(m_Camera->m_Right, 0.0);
        m_Camera->m_Up = rotateMatrix * glm::vec4(m_Camera->m_Up, 0.0);
    }
}